package com.example.消息可靠性.发送方保证.发送方确认机制;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 */
@Configuration
public class ConfirmConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {
    public static final String CONFIRM_QUEUE = "confirm_queue";
    public static final String CONFIRM_EXCHANGE = "confirm_exchange";

    @Bean
    Queue confirmQueue() {
        return new Queue(CONFIRM_QUEUE, true, false, false);
    }

    /**
     * 定义一个直连交换机
     *
     * @return
     */
    @Bean
    DirectExchange confirmExchange() {
        //1. 交换机的名称
        //2。交换机是否持久化
        //3. 如果没有与之绑定的队列，是否删除交换机
        return new DirectExchange(CONFIRM_EXCHANGE, true, false);
    }

    /**
     * 这个定义是将交换机和队列绑定起来
     *
     * @return
     */
    @Bean
    Binding tranBinding() {
        return BindingBuilder
            .bind(confirmQueue()).to(confirmExchange()).with(CONFIRM_QUEUE);
    }

    /**
     * 消息成功到达交换机的回调方法
     * @param correlationData
     * @param ack
     * @param cause
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(ack){
            System.out.println(String.format("%s消息成功到达交换机",correlationData.getId()));
        }else {
            System.out.println(String.format("%s消息没有成功到达交换机",correlationData.getId()));
        }
    }

    /**
     * 消息未成功到达队列的回调方法
     * @param returned
     */
    @Override
    public void returnedMessage(ReturnedMessage returned) {
        System.out.println("消息未成功到达队列");
    }

    @Autowired
    RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void initRabbitTemplate(){
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this::returnedMessage);
    }
}
